<?php

class BaseModel extends Model {
	
	protected $publicdata;
	
	protected $id;
	public $data;
	public $statuses = array('active', 'deprecated', 'deleted');
	
	private $idfield;
	private $tblname;
	private $versionned;
	
	function BaseModel($tblname, $idfield, $publicdata, $versionned = true) {
		parent::Model();
		$this->tblname = $tblname;
		$this->idfield = $idfield;
		$this->versionned = $versionned;
		$this->publicdata = $publicdata;
	}
	
	/**
	 * Returns the next version number of the databse
	 */
	private function get_next_db_version() {
		$this->db->query('UPDATE cr_config SET value = LAST_INSERT_ID(value+1) WHERE name = \'db_version\'');
		$query = $this->db->query('SELECT LAST_INSERT_ID() last_id');
		$array = $query->result_array();
		return $array[0]['last_id'];
	}
	
    /**
     * Loads the data referenced as prepared through the db library
     */
    protected function load() {
    	$this->db->from($this->tblname);
    	$query = $this->db->get();
		if ($query->num_rows() < 1)
			return FALSE;
    	$this->data = $query->row_array();
    	
    	//Separates sensitive data from the public data
		$this->id = $this->data[$this->idfield];
    
    	return TRUE;
    }
    
    /**
     * Copies from $src to $dst the fields that are allowed to change
     */
    private function copy_public_data($src, &$dst) {
		foreach ($this->publicdata as $key) {
			if (isset($src[$key]))
				$dst[$key] = $src[$key];
		}
    }
	
    /**
     * Creates a new element using this $data
     * Returns  true if the element was successfully created
     * 			an array mapping error messages onto bad fields if it failed 
     */
    protected function new_data($data, $checkeddata = null) {
		$this->data = array();
		$this->copy_public_data($data, $this->data);
		if ($checkeddata)
			$this->data = array_merge($this->data, $checkeddata);

		$errors = $this->fields_are_valid($this->data);
		if (is_array($errors))
			return $errors;

    	if ($this->versionned)
			$this->data['db_version'] = $this->get_next_db_version();

    	//name is free, inserting the data in the database
    	$this->db->insert($this->tblname, $this->data);
    	//we should check whether data has been inserted
        return true;
    }
	
	/**
	 * Stores one element's information in the database
     * Returns  true if the element was successfully updated
     * 			an array mapping error messages onto bad fields if it failed 
	 */
	function save_data($id, $data, $checkeddata = null) {
		$errors = $this->fields_are_valid($data);
		if (is_array($errors))
			return $errors;
		//saving all informations, even those who may have not changed
		$pubarray = array();
		$this->copy_public_data($data, $pubarray);
    	if ($this->versionned)
			$pubarray['db_version'] = $this->get_next_db_version();
		if ($checkeddata)
			$pubarray = array_merge($pubarray, $checkeddata);
		$this->db->where($this->idfield, $id);
		$this->db->update($this->tblname, $pubarray);
		return TRUE;
	}
	
	/**
	 * Checks the validity of the infos stored in the $data array
	 * Returns an array mapping error messages onto bad fields
	 */
	protected function fields_are_valid($data) {
		return array('nofield' => 'Fields were unchecked');
	}

	/**
	 * Returns whether a branch with this name exists or not
	 */
	function exists($where) {
		if ($where)
			foreach ($where as $key => $value) 
    			$this->db->where($key, $value);
		$query = $this->db->get($this->tblname);
		return ($query->num_rows() > 0);
	}

    /**
	 * Returns an array of $count elements starting with the $first
	 * If $count is null, returns all values
	 * This array is sorted on the $sorted column
	 * $match is an array containg a key and a value which is to match.
	 * ie : $match = array ($field => $namematch)
	 */
	function get_data($first = null, $count = null, $sorted = null, $match = null) {
		if ($match)
			foreach ($match as $key => $value)
				$this->db->like($key, $value);
		if ($sorted)
			$this->db->orderby($sorted);
		$this->db->from($this->tblname);
		if ($count)
			$query = $this->db->get('', $count, $first);
		else
			$query = $this->db->get();
		return $query->result_array();
	}
	
    /**
     * Returns the total number of elements
	 * $match is an array containg a key and a value which is to match.
	 * ie : $match = array ($field => $namematch)
	 */
	function get_data_count($match = null) {
		if ($match) {
			foreach ($match as $key => $value)
				$this->db->like($key, $value);
			$this->db->select('COUNT(*) nbmatch');
			$query = $this->db->get($this->tblname);
			$array = $query->result_array();
			return $array[0]['nbmatch'];
		}
		return $this->db->count_all($this->tblname);
	}

}

?>
